﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MapSurface.UIModelElement;
using System.Xml;

namespace MapSurface.AssemblyReflexion
{
   public class ChoiceManager
    {
        private ChoiceTable _model;
        private AssemblyReflexion _assembly;
        public APIModelManager apiModel;

        public ChoiceTable Model
        {
            get { return _model; }
            set { _model = value; }
        }
        private XmlDocument _docXML;

        public ChoiceManager(String Choicefile, string dllFile,List<Delegate> selectHandler)
        {
            try
            {
                _docXML = new XmlDocument();
                _docXML.Load(Choicefile);
                _model = build(_docXML.DocumentElement, Choicefile);
                _assembly = new AssemblyReflexion(dllFile, selectHandler);
            }
            catch (Exception)
            {
                throw new Exception();
            }
        }
        public ChoiceTable build(XmlElement root, string xmiFile)
        {
            if (root.Name.Contains("ChoiceModel"))
            {
                String name = "";
                if (root.Attributes.GetNamedItem("name") != null)
                    name = root.Attributes.GetNamedItem("name").Value;
                ChoiceTable model = new ChoiceTable(name);
                if (root.HasChildNodes)
                {//uielements
                    model.FuiElement = new List<FUIElement>();
                    foreach (XmlNode node in root.ChildNodes)
                    {
                        model.FuiElement.Add((FUIElement)build(node));
                    }
                }
                return model;
            }
            return null;
        }
        public FUIElement build(XmlNode node)
        {

            FUIElement el = null;
            if (node.HasChildNodes)
            {   foreach (XmlNode ni in node.ChildNodes)
                {
                    if (ni.Name.CompareTo("uielement") == 0)
                    {
                        UIElement elme ;
                        if (!isContainer(ni))
                            elme = new UIElement(ni);
                        else elme = new Container(ni);
                        el = new FUIElement(node.Attributes.GetNamedItem("name").Value, node.Attributes.GetNamedItem("widgetType").Value, elme);
                    }
                }
                 if (el != null )
                foreach(XmlNode ni in node.ChildNodes)
                {
                    if ( ni.Name.CompareTo("widgets") == 0)
                    {
                        UIElement elme = null;
                        if (ni.HasChildNodes)
                            foreach (XmlNode nx in ni.ChildNodes)
                                if (nx.Name.CompareTo("uielement") == 0)
                                {
                                    if (!isContainer(nx))
                                        elme = new UIElement(nx);
                                    else elme = new Container(nx);
                                    if (elme.XamlNode == null)
                                        Console.Out.WriteLine();

                                }
                        Equivalent eq = new Equivalent(ni.Attributes.GetNamedItem("name").Value, ni.Attributes.GetNamedItem("widgetType").Value, elme);
                        if (el.Equivalents == null)
                            el.Equivalents = new List<Equivalent>();
                        el.Equivalents.Add(eq);
                    }
                }
            }
            return el;
        }

        private bool isContainer(XmlNode nodew)
        {
            if (nodew.HasChildNodes && nodew.Name.CompareTo("uielement")==0)
                foreach(XmlNode c in nodew)
                    if (c.Name.CompareTo("widgetType") == 0)
                        if (c.Attributes.GetNamedItem("isContainer") != null && c.Attributes.GetNamedItem("isContainer").Value != null)
                            return Boolean.Parse(c.Attributes.GetNamedItem("isContainer").Value);
            return false;
        }
        public UIElement createUIelement(XmlNode node)
        {
            if (node.HasChildNodes)
                foreach (XmlNode ni in node.ChildNodes)
                {
                    if (ni.Name.CompareTo("uielement") == 0)
                    {
                        if (isContainer(ni))
                            return new Container(ni);
                        else
                            return new UIElement(ni);
                    }
                }
            return null;
        }
        public List<Object> getEquivalentInstance(UIElement current)
        {
            List<Object> lo = new List<object>();
            if (_model.FuiElement != null)
                foreach (FUIElement f in _model.FuiElement)
                {
                    if (f.WidgetType.CompareTo(current.WidgetType.Name) == 0)
                    {
                        if (f.Equivalents != null)
                            foreach (Equivalent eq in f.Equivalents)
                                if(eq.UIelement.getBehaviour().Count>=current.getBehaviour().Count)
                                    lo.Add(_assembly.getInstance(eq.WidgetType, current));
                        break;
                    }
                }
            return lo;
        }

        public List<Object> getEquivalentInstance(Widget widget)
        {
            List<Object> lo = new List<object>();
            if (_model !=null &&_model.FuiElement != null)
                foreach (FUIElement f in _model.FuiElement)
                {
                    if (f.WidgetType.CompareTo(widget.Name) == 0)
                    {
                        if (f.Equivalents != null)
                            foreach (Equivalent eq in f.Equivalents)
                            {
                                //if (w.getBehaviour().Count >= widget.getBehaviour().Count)
                                {
                                    lo.Add(_assembly.getInstance(eq.WidgetType,eq.UIelement));
                                }
                            }
                        break;
                    }
                    if (f.Equivalents != null)
                    {
                        bool equa = false;
                        foreach (Equivalent eq in f.Equivalents)
                        {
                            if (eq.WidgetType.CompareTo(widget.Name) == 0)
                                equa = true;
                            if (equa)
                            {
                                Widget w = apiModel.findWidget(f.WidgetType);
                                if (lo.Count == 0)
                                    lo.Add(_assembly.getInstance(w));
                                foreach( Equivalent equi in f.Equivalents)
                                    if (equi.WidgetType.CompareTo(eq.WidgetType) != 0 )
                                    {
                                        w = apiModel.findWidget(equi.WidgetType);
                                        if(w.getBehaviour().Count>=widget.getBehaviour().Count)
                                            lo.Add(_assembly.getInstance(equi.WidgetType,equi.UIelement));                    
                                    }
                                break;
                            }
                        }
                    }
                }

            return lo;
        }
        public List<Object> getEquivalentInstance(Widget widget, object instance)
        {
            String name=_assembly.getAttribute(instance, "Name");
            List<String> type = new List<string>();
            List<Object> lo = new List<object>();
            if (_model != null && _model.FuiElement != null)
                foreach (FUIElement f in _model.FuiElement)
                {
                    if (f.WidgetType.CompareTo(widget.Name) == 0 )
                    {
                        if (f.Equivalents != null)
                            foreach (Equivalent eq in f.Equivalents)
                            {
                                if (!type.Contains(eq.WidgetType))
                                {
                                    type.Add(eq.WidgetType);
                                    lo.Add(_assembly.getInstance(eq.WidgetType, eq.UIelement));
                                }
                            }
                        if(name.CompareTo(f.UIelement.Name)==0)
                            break;
                    }
                    if (f.Equivalents != null)
                    {
                        bool equa = false;
                        foreach (Equivalent eq in f.Equivalents)
                        {
                            if (eq.WidgetType.CompareTo(widget.Name) == 0 && f.UIelement.Name.CompareTo(name) == 0)
                                equa = true;
                            if (equa)
                            {
                                Widget w = apiModel.findWidget(f.WidgetType);
                                if (lo.Count == 0)
                                    lo.Add(_assembly.getInstance(w.Name,f.UIelement));
                                foreach (Equivalent equi in f.Equivalents)
                                    if (equi.WidgetType.CompareTo(eq.WidgetType) != 0)
                                    {
                                        w = apiModel.findWidget(equi.WidgetType);
                                        if (w.getBehaviour().Count >= widget.getBehaviour().Count)
                                            if (!type.Contains(eq.WidgetType))
                                            {
                                                type.Add(eq.WidgetType);
                                                lo.Add(_assembly.getInstance(equi.WidgetType, equi.UIelement));
                                            }
                                    }
                                break;
                            }
                        }
                    }
                }

            return lo;
        }

        public UIElement findUIElement(object instance)
        {
            foreach (FUIElement f in _model.FuiElement)
            {
                if (f.WidgetType.CompareTo(instance.GetType().Name) == 0 && ((System.Windows.FrameworkElement)instance).Name.CompareTo(f.UIelement.Name)==0)
                    return f.UIelement;
                else if (f.Equivalents != null)
                    foreach (Equivalent eq in f.Equivalents)
                        if (eq.WidgetType.CompareTo(instance.GetType().Name) == 0 && ((System.Windows.FrameworkElement)instance).Name.CompareTo(eq.UIelement.Name) == 0)
                            return eq.UIelement;
            }
            return null;
        }
    }

}
